Js正则表达式

2018.12.10 星期一 12:33

RegExp:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp

语法

字面量, 构造函数和工厂符号都是可以的:
/pattern/flags
new RegExp(pattern [, flags])
RegExp(pattern [, flags])

m:多行; 将开始和结束字符(^和$)视为在多行上工作(也就是,分别匹配每一行的开始和结束(由 \n 或 \r 分割),而不只是只匹配整个输入字符串的最开始和最末尾处。
y:粘性匹配; 仅匹配目标字符串中此正则表达式的lastIndex属性指示的索引(并且不尝试从任何后续的索引匹配)。

描述

1
2
3
/ab+c/i;
new RegExp('ab+c', 'i');
new RegExp(/ab+c/, 'i');

正则表达式中特殊字符的含义

字符类别(Character Classes):\d,\D,\w,...
字符集合(Character Sets): [],[^],[1-9]
边界(Boundaries):\b,\B,^,$
分组(grouping)与反向引用(back references):(x),(?:x),\n
数量词(Quantifiers):*,*?,+,+?,? ?=,?!,|, {n},{n,},{n,m}
断言(Assertions): x(?=y), x(?!y)

.:(点号,小数点) 匹配任意单个字符,但是行结束符除外:\n \r \u2028 或 \u2029。
在字符集中,点( . )失去其特殊含义,并匹配一个字面点( . )。
需要注意的是,m 多行(multiline)标志不会改变点号的表现。因此为了匹配多行中的字符集,可使用[^] (当然你不是打算用在旧版本 IE 中),它将会匹配任意字符,包括换行符。

[\b]匹配一个退格符(backspace)(不要与 \b 混淆)

(x):匹配 x 并且捕获匹配项。 这被称为捕获括号(capturing parentheses)。
例如,/(foo)/ 匹配且捕获 “foo bar.” 中的 “foo”。被匹配的子字符串可以在结果数组的元素 [1], …, [n] 中找到,或在被定义的 RegExp 对象的属性 $1, …, $9 中找到。
捕获组(Capturing groups)有性能惩罚。如果不需再次访问被匹配的子字符串,最好使用非捕获括号(non-capturing parentheses),见下面。

(?:x):匹配 x 不会捕获匹配项。这被称为非捕获括号(non-capturing parentheses)。匹配项不能够从结果数组的元素 [1], …, [n] 或已被定义的 RegExp 对象的属性 $1, …, $9 再次访问到。

属性

RegExp.prototype:允许为所有正则对象添加属性。
RegExp.length:值为 2。
Properties inherited from Function:arity, caller, constructor, length, name

方法

全局对象 RegExp 自身没有方法, 不过它会继承一些方法通过原型链
Methods inherited from Function:apply, call, toSource, toString

RegExp 实例

属性

RegExp.prototype.constructor
RegExp.prototype.global
RegExp.prototype.ignoreCase
RegExp.prototype.lastIndex
RegExp.prototype.multiline:是否开启多行模式匹配(影响 ^ 和 $ 的行为)。
RegExp.prototype.source:正则对象的源模式文本。
RegExp.prototype.sticky :是否开启粘滞匹配。
Properties inherited from Object:__parent__, __proto__

方法

RegExp.prototype.exec()
RegExp.prototype.test()
RegExp.prototype.toSource() :返回一个字符串,其值为该正则对象的字面量形式。覆盖了Object.prototype.toSource 方法.
RegExp.prototype.toString():返回一个字符串,其值为该正则对象的字面量形式。覆盖了
Methods inherited from Object:

例子

+++++++++++++++++++

RegExp.prototype.exec()

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec

如果匹配成功,exec() 方法返回一个数组,并更新正则表达式对象的属性。返回的数组将完全匹配成功的文本作为第一项,将正则括号里匹配成功的作为数组填充到后面。
如果匹配失败,exec() 方法返回 null。

### result:
[0] 匹配的全部字符串
[1], …[n ] : 括号中的分组捕获
index:匹配到的字符位于原始字符串的基于0的索引值
input:原始字符串
### re
lastIndex: 下一次匹配开始的位置 25
ignoreCase: 是否使用了 “i” 标记使正则匹配忽略大小写 true
global: 是否使用了 “g” 标记来进行全局的匹配. true
multiline: 是否使用了 “m” 标记使正则工作在多行模式(也就是,^ 和 $ 可以匹配字符串中每一行的开始和结束(行是由 \n 或 \r 分割的),而不只是整个输入字符串的最开始和最末尾处。)

false
source 正则匹配的字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var regex1 = RegExp('foo*.','g');
var str1 = 'table football, foosball';
var array1;

while ((array1 = regex1.exec(str1)) !== null) {
console.log(`Found ${array1[0]}. Next starts at ${regex1.lastIndex}.`);
// expected output: "Found foot. Next starts at 9."
// expected output: "Found foos. Next starts at 19."
}

// ## return
var re = /quick\s(brown).+?(jumps)/ig;
var result = re.exec('The Quick Brown Fox Jumps Over The Lazy Dog');
// (3) ["Quick Brown Fox Jumps", "Brown", "Jumps", index: 4, input: "The Quick Brown Fox Jumps Over The Lazy Dog", groups: undefined]

示例

### 查找所有匹配
当正则表达式使用 “g” 标志时,可以多次执行 exec 方法来查找同一个字符串中的成功匹配。
当你这样做时,查找将从正则表达式的 lastIndex 属性指定的位置开始。(test() 也会更新 lastIndex 属性)。

注意:不要把正则表达式字面量(或者RegExp构造器)放在 while 条件表达式里。由于每次迭代时 lastIndex的属性都被重置,如果匹配,将会造成一个死循环。并且要确保使用了’g’标记来进行全局的匹配,否则同样会造成死循环。

### 结合 RegExp 字面量使用 exec()
你也可以直接使用 exec() 而不是创建一个 RegExp 对象:

1
2
var matches = /(hello \S+)/.exec('This is a hello world!');
console.log(matches[1]); // hello world!

RegExp.prototype.test()

描述

当你想要知道一个模式是否存在于一个字符串中时,就可以使用 test()(类似于 String.prototype.search() 方法),
差别在于test返回一个布尔值,而 search 返回索引(如果找到)或者-1(如果没找到);
若想知道更多信息(然而执行比较慢),可使用exec() 方法(类似于 String.prototype.match() 方法)。
和 exec() (或者组合使用),一样,在相同的全局正则表达式实例上多次调用test将会越过之前的匹配。

示例

1
2
3
4
5
6
7
var regex = /foo/g;

// regex.lastIndex is at 0
regex.test('foo'); // true

// regex.lastIndex is now at 3
regex.test('foo'); // false

RegExp.$1-$9

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp/n

该特性是非标准的,请尽量不要在生产环境中使用它!

描述

$1, …, $9 属性是静态的, 他不是独立的的正则表达式属性. 所以, 我们总是像这样子使用他们RegExp.$1, …, RegExp.$9.

属性的值是只读的而且只有在正确匹配的情况下才会改变.

括号匹配项是无限的, 但是RegExp对象能捕获的只有九个. 你可以通过返回一个数组索引来取得所有的括号匹配项.

这些属性可以在String.replace 方法中替换字符串. 在这种情况下, 不用在前面加上RegExp。下面的例子将详细说明. 当正则表达式中不包含括号, 脚本中的 $n’s 就是字面上的意思 (当n是正整数).

例子

$n 在 String.replace中的应用节
以下脚本用 replace() 方法去匹配一个first last格式的 nameString 实例 输出last first格式. 在替换文本里, 脚本用 $1 和 $2 表示正则表达式中的括号匹配项的结果.

1
2
3
4
5
var re = /(\w+)\s(\w+)/;
var str = 'John Smith';
str.replace(re, '$2, $1'); // "Smith, John"
RegExp.$1; // "John"
RegExp.$2; // "Smith"

\===========================================
和正则相关的字符串API
# String.prototype.search()
str.search(regexp)
如果匹配成功,则 search() 返回正则表达式在字符串中首次匹配项的索引。否则,返回 -1。

# String.prototype.match()

语法

返回值:array
如果字符串匹配到了表达式,会返回一个数组,数组的第一项是进行匹配完整的字符串,之后的项是用圆括号捕获的结果。如果没有匹配到,返回null

描述

如果正则表达式不包含 g 标志,则 str.match() 会返回和 RegExp.exec() 相同的结果。而且返回的 Array 拥有一个额外的 input 属性,该属性包含被解析的原始字符串。另外,还拥有一个 index 属性,该属性表示匹配结果在原字符串中的索引(以0开始)。

如果正则表达式包含 g 标志,则该方法返回一个 Array ,它包含所有匹配的子字符串而不是匹配对象。捕获组不会被返回(即不返回index属性和input属性)。如果没有匹配到,则返回 null 。

### API选择
如果你需要知道一个字符串是否匹配一个正则表达式 RegExp ,可使用 search() 。
如果你只是需要第一个匹配结果,你可能想要使用 RegExp.exec() 。($PS:不是match吗)
如果你想要获得捕获组,并且设置了全局标志,你需要用 RegExp.exec() 。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// \### 例子:使用 match   
var str = 'For more information, see Chapter 3.4.5.1';
var re = /see (chapter \d+(\.\d)*)/i;
var found = str.match(re);
// (3) ["see Chapter 3.4.5.1", "Chapter 3.4.5.1", ".1", index: 22, input: "For more information, see Chapter 3.4.5.1", groups: undefined]
// '.1' 是被'(\.\d)'捕获的最后一个值。

// ### 例子:match 使用全局(global)和忽略大小写(ignore case)标志
var str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
var regexp = /[A-E]/gi;
var matches_array = str.match(regexp);
console.log(matches_array); // ['A', 'B', 'C', 'D', 'E', 'a', 'b', 'c', 'd', 'e']

// ### 使用match(),不传参数 节
var str = "Nothing will come of nothing.";
str.match(); // returns [""]

// ### 一个非正则表达式对象作为参数
// 当参数是一个字符串或一个数字,它会使用new RegExp(obj)来隐式转换成一个 RegExp。如果它是一个有正号的正数,RegExp() 方法将忽略正号。

var str1 = "NaN means not a number. Infinity contains -Infinity and +Infinity in JavaScript.",
str2 = "My grandfather is 65 years old and My grandmother is 63 years old.",
str3 = "The contract was declared null and void.";
str1.match("number"); // "number" 是字符串。返回["number"]
str1.match(NaN); // NaN的类型是number。返回["NaN"]
str1.match(Infinity); // Infinity的类型是number。返回["Infinity"]
str1.match(+Infinity); // 返回["Infinity"]
str1.match(-Infinity); // 返回["-Infinity"]
str2.match(65); // 返回["65"]
str2.match(+65); // 有正号的number。返回["65"]
str3.match(null); // 返回["null"]

String.prototype.replace()

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/replace

注意:原字符串不会改变。

语法

str.replace(regexp|substr, newSubStr|function)
regexp (pattern):一个RegExp 对象或者其字面量。该正则所匹配的内容会被第二个参数的返回值替换掉。
substr (pattern):一个要被 newSubStr 替换的字符串。其被视为一整个字符串,而不是一个正则表达式。仅仅是第一个匹配会被替换。
newSubStr (replacement): 用于替换掉第一个参数在原字符串中的匹配部分的字符串。该字符串中可以内插一些特殊的变量名。参考下面的使用字符串作为参数。
function (replacement):一个用来创建新子字符串的函数,该函数的返回值将替换掉第一个参数匹配到的结果。参考下面的指定一个函数作为参数。

描述

该方法并不改变调用它的字符串本身,而只是返回一个新的替换后的字符串。
在进行全局的搜索替换时,正则表达式需包含 g 标志。

使用字符串作为参数

替换字符串可以插入下面的特殊变量名:
变量名 代表的值
$$插入一个 “$”。
$& 插入匹配的子串。
$` 插入当前匹配的子串左边的内容。
$’ 插入当前匹配的子串右边的内容。
$n 假如第一个参数是 RegExp对象,并且 n 是个小于100的非负整数,那么插入第 n 个括号匹配的字符串。提示:索引是从1开始

指定一个函数作为参数

你可以指定一个函数作为第二个参数。在这种情况下,当匹配执行后, 该函数就会执行。
函数的返回值作为替换字符串。 (注意: 上面提到的特殊替换参数在这里不能被使用。)
另外要注意的是, 如果第一个参数是正则表达式, 并且其为全局匹配模式, 那么这个方法将被多次调用, 每次匹配都会被调用。

下面是该函数的参数:
变量名 代表的值
match 匹配的子串。(对应于上述的$&。)
p1,p2, … 假如replace()方法的第一个参数是一个RegExp 对象,则代表第n个括号匹配的字符串。(对应于上述的$1,$2等。)
offset 匹配到的子字符串在原字符串中的偏移量。(比如,如果原字符串是“abcd”,匹配到的子字符串是“bc”,那么这个参数将是1)
string 被匹配的原字符串。

(精确的参数个数依赖于replace()的第一个参数是否是一个正则表达式对象, 以及这个正则表达式中指定了多少个括号子串。)

1
2
3
4
5
6
function replacer(match, p1, p2, p3, offset, string) {
// p1 is nondigits, p2 digits, and p3 non-alphanumerics
return [p1, p2, p3].join(' - ');
}
var newString = 'abc12345#$*%'.replace(/([^\d]*)(\d*)([^\w]*)/, replacer);
console.log(newString); // abc - 12345 - #$*%

示例

### 1 在 replace() 中使用正则表达式
### 2 在 replace() 中使用 global 和 ignore 选项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// \### 3 交换字符串中的两个单词     
var re = /(\w+)\s(\w+)/;
var str = "John Smith";
var newstr = str.replace(re, "$2, $1"); // Smith, John
// \### 4 使用行内函数来修改匹配到的字符。
function styleHyphenFormat(propertyName) {
function upperToHyphenLower(match) {
return '-' + match.toLowerCase();
}
return propertyName.replace(/[A-Z]/g, upperToHyphenLower);
}
// styleHyphenFormat('borderTop') 将返回 'border-top'。
// var newString = propertyName.replace(/[A-Z]/g, '-' + '$&'.toLowerCase()); // won't work

// ### 5 将华氏温度转换为对等的摄氏温度
function f2c(x){
function convert(str, p1, offset, s){
return ((p1-32) * 5/9) + "C";
}
var s = String(x);
var test = /(\d+(?:\.\d*)?)F\b/g;
return s.replace(test, convert);
}

// ### 6 使用行内函数和正则来避免循环节
// 下例把某种模式的字符串转换为一个对象数组(其元素为对象)。
// 输入:一个由 x,- 和 _ 组成的字符串。
// 输出:一个数组对象。'x' 产生一个 'on' 状态,'-'(连接符)产生一个 'off' 状态,而 '_' (下划线)表示 'on' 状态的长度。
var str = 'x-x_'; // 1
// var str='---x---x---x---' // 2
var str = '_x_x___x___x___'; // 3
var retArr = [];
str.replace(/(x_*)|(-)/g, function(match, p1, p2) {
if (p1) { retArr.push({ on: true, length: p1.length }); }
if (p2) { retArr.push({ on: false, length: 1 }); }
});

console.log(retArr);
// [{ on: true, length: 1 },{ on: false, length: 1 },{ on: true, length: 2 }] //1
// [{on: true, length: 2}, {on: true, length: 4},{on: true, length: 4},{on: true, length: 4}] // 3

19:32

knowledge is no pay,reward is kindness
0%